﻿using System;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using EvoGame.Core.Components;
using EvoGame.Core.Interfaces;

namespace EvoGame.Core.Files
{
	public static partial class FileHandler
	{
		public class XML : File, ILoadable, ISaveable
		{
			protected override FileStream fileStream
			{
				get { return this.file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); }
			}

			protected XDocument xmlDoc;
			protected XDocument header;
			protected XNamespace xmlNS;

			private XmlReader xmlRead;
			private XmlWriter xmlWrite;

			public XML(string path)
				: this(path, new XDocument(new XComment("edited with " + EvoApp.FormattedVersion), new XComment(((AssemblyCopyrightAttribute)Assembly.GetEntryAssembly().GetCustomAttributes(typeof (AssemblyCopyrightAttribute), false)[0]).Copyright), new XComment("")))
			{ }

			public XML(string path, XDocument head)
				: base(path)
			{
				this.header = head;
				this.xmlRead = XmlReader.Create(this.fileStream);
				this.xmlWrite = XmlWriter.Create(this.fileStream);
			}

			public virtual void Load()
			{
				this.xmlDoc = XDocument.Load(this.xmlRead);
				this.xmlNS = this.xmlDoc.Root.Name.Namespace;
			}

			public virtual void Save()
			{
				this.xmlDoc.AddFirst(this.header.Nodes());
				this.xmlDoc.WriteTo(this.xmlWrite);
			}

			public override void Close()
			{
				this.xmlRead.Close();
				this.xmlWrite.Close();
				this.fileStream.Close();
			}

			public static XElement GetRawData(XElement xe, string tag)
			{
				XNamespace ns = xe.Name.Namespace;
				try
				{
					return xe.Element(ns.GetName(tag));
				}
				catch (NullReferenceException nre)
				{
					if (EvoApp.Debug)
						EvoApp.Debug.Output = string.Format("Tag \"{0}\" is missing:{1}\t{2}", tag, Environment.NewLine, nre.Message);
					return null;
				}
			}

			public static string GetStringData(XElement xe, string tag)
			{
				try
				{
					return GetRawData(xe, tag).Value;
				}
				catch (NullReferenceException nre)
				{
					if (EvoApp.Debug)
						EvoApp.Debug.Output = string.Format("Tag \"{0}\" is missing:{1}\t{2}", tag, Environment.NewLine, nre.Message);
					return "NULL";
				}
			}

			public static bool GetBoolData(XElement xe, string tag)
			{
				return Convert.ToBoolean(int.Parse(GetStringData(xe, tag)));
			}

			public static int GetIntData(XElement xe, string tag)
			{
				return int.Parse(GetStringData(xe, tag));
			}

			public static float GetFloatData(XElement xe, string tag)
			{
				return float.Parse(GetStringData(xe, tag));
			}
		}
	}
}
